#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time      : 2018/12/12 9:58
# @Author    : lmh
# @File      : monitor.py
#
#
import sys
import requests
import json
import subprocess
from subprocess import Popen
import os
import psutil
import datetime
import time


def sendMsg(msg, env):
    print(msg + "，当前环境：" + env)
    if env == "test":
        print("测试无需发送钉钉通知")
        return
    url = "https://oapi.dingtalk.com/robot/send?access_token=0e7325f047df73fe31890b20a2476b3c934bc624312db6c6468299a0697bfa80"
    message = {"content": msg}
    body = {"msgtype": "text", "text": message}
    headers = {'content-type': "application/json"}
    response = requests.post(url, data=json.dumps(body), headers=headers)
    print(response.text)


def openBat(file_path):
    time.sleep(2)
    runAdmin(file_path)
    # Popen(file_path, creationflags=subprocess.CREATE_NEW_CONSOLE)


def getPids(jiqiren, name, bat):
    time.sleep(5)
    pids = psutil.pids()
    ppid = ''
    for pid in pids:
        p = psutil.Process(pid)
        if p.name() == name:
            ppid = pid
            # print("已经启动," + name)
            break
    if ppid == '':
        print(name + "正在准备启动")
        openBat(bat)
        print(name + "启动成功")
        ppid = getPids(jiqiren, name, bat)
        print(ppid)
    return ppid


def monitor(pidp, mName, bat, processName, env):
    try:
        start = datetime.datetime.now()
        # # 设定监控时间  默认3天
        CYCLE_TIME = datetime.timedelta(weeks=0, days=365, hours=00, minutes=0, seconds=5, microseconds=0,
                                        milliseconds=0)  # 60*60*24
        start_time = datetime.datetime.today()
        # 判断进程是否存在
        if (psutil.pid_exists(pidp)):
            p = psutil.Process(pidp)  # 实例化一个进程
            pName = p.name()  # 进程名
            # 设置日志名
            # logName = pName + "_" + str(pidp) + "_stress_monitoring_record.log"  # log文件
            # logfile = open(logName, "a")
        else:
            print("pid is not exists please enter true pid!!!")
            return
        wTime = 10  # 等待时间
        while (True):
            # 判定监控时间
            if ((datetime.datetime.today() - start_time) > CYCLE_TIME):
                break
            recTime = time.strftime('%Y-%m-%d\t%H:%M:%S',
                                    time.localtime(time.time()))  # datetime.datetime.today() #记录时间
            # 判断进程是否存在
            if (psutil.pid_exists(pidp)):
                vmm = p.memory_info().vms  # 虚存 单位字节
                mm = p.memory_info().rss  # 实际使用内存 单位字节
                pCpu = p.cpu_percent(interval=1)  # CPU百分比
                nThreads = p.num_threads()  # 线程数
                nHandles = p.num_handles()  # 句柄数
                maxMm = 12867993600
                maxCpu = 100
                # 记录进程详细信息
                log_msg = str(recTime) + "\t" + "虚存:" + str(vmm) + "\t" + "实际使用内存:" + str(
                    mm) + "\t" + "CPU百分比:" + str(pCpu) + "\t" + "线程数:" + str(
                    nThreads) + "\t" + "句柄数:" + str(nHandles) + "\n"
                if mm >= maxMm:
                    end = datetime.datetime.now()
                    t3 = end - start
                    pushMsg = mName + "cpu占用过高,内存过载，正在准备重启,最近一次在线" + str(t3.days) + "天,具体在线时长：" + str(t3) + "。详细信息："
                    sendMsg(pushMsg + log_msg, env)
                    p.terminate()  # 结束进程
                    openBat(bat)
                    time.sleep(2)
                    succ = "启动成功"
                    sendMsg(mName + succ, env)
                    pid_str_p = getPids(mName, processName, bat)
                    if pid_str_p == '':
                        pidp = int(pid_str_p)
                        monitor(pidp, mName, bat, processName, env)
                    else:
                        pidp = int(pid_str_p)
                        monitor(pidp, mName, bat, processName, env)
            else:
                log_msg = str(datetime.datetime.today()) + "\t" + str(pidp) + "  is not running!!!!!!!!!\n"
                print(log_msg)
                end = datetime.datetime.now()
                t3 = end - start
                pushMsg = mName + "进程消失，正在重启,最近一次在线" + str(t3.days) + "天,具体在线时长：" + str(t3)
                sendMsg(pushMsg, env)
                openBat(bat)
                time.sleep(2)
                succ = "启动成功"
                sendMsg(mName + succ, env)
                pid_str_p = getPids(mName, processName, bat)
                if pid_str_p == '':
                    pid_str_p = getPids(mName, processName, bat)
                    pidp = int(pid_str_p)
                    monitor(pidp, mName, bat, processName, env)
                else:
                    pidp = int(pid_str_p)
                    monitor(pidp, mName, bat, processName, env)
                # break
            print(log_msg)
            # logfile.flush()
            # logfile.write(log_msg)  # 写入log文件
            time.sleep(wTime)  # 循环等待
        # logfile.close()
    except Exception as e:
        print(e)
        openBat(bat)
        time.sleep(20)
        ppidx = getPids(mName, processName, bat)
        pidx = int(ppidx)
        monitor(pidx, mName, bat, processName, env)


def runAdmin(cmd, timeout=1800000):
    f = None
    try:
        bat = os.getcwd() + r"\pddCmd.bat"
        f = open(bat, 'w')
        f.write(cmd)
    except Exception as e:
        raise e
    finally:
        if f:
            f.close()

    try:
        shell = os.getcwd() + r"\shell.vbs"
        sp = subprocess.Popen(
            shell,
            shell=True,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE
        )
        print("[PID] %s: %s" % (sp.pid, cmd))
        sp.wait(timeout=timeout)

        stderr = str(sp.stderr.read().decode("gbk")).strip()
        stdout = str(sp.stdout.read().decode("gbk")).strip()
        if "" != stderr:
            raise Exception(stderr)
        if stdout.find("失败") > -1:
            raise Exception(stdout)
    except Exception as e:
        raise e


if __name__ == "__main__":
    jiqiren = input("请输入当前登录的机器人：")
    env = input("请选择测试或者发布：测试请输入test,否则输入prd：")
    batPath = "@echo off" + "\n\r" + "call D:\pdd-tools\PDD\zuhaohao2.bat" + "\n\r" + "echo over" + "\n\r""exit"
    # batPath = "HappyGo.exe" + "\t" + '"' + "C:\\Program Files (x86)\\pinduoduo\\2.6.4.19\\PddWorkbench.exe" + '"' + "\t" + "zuhaohao2.ini"
    processName = 'PddWorkbench.exe'
    # batPath = "I:\\PotPlayer\\PotPlayerMini.exe"
    # processName = 'PotPlayerMini.exe'
    pid_str = getPids(jiqiren, processName, batPath)
    if pid_str == '':
        print("pid is not exists please enter true pid!!!")
        openBat(batPath)
        time.sleep(10)
        ppid = getPids(jiqiren, processName, batPath)
        pid = int(ppid)
        monitor(pid, jiqiren, batPath, processName, env)
    else:
        if pid_str == '':
            print("pid is not exists please enter true pid!!!")
            openBat(batPath)
            ppid = getPids(jiqiren, processName, batPath)
            pid = int(ppid)
            monitor(pid, jiqiren, batPath, processName, env)
        else:
            pid = int(pid_str)
            monitor(pid, jiqiren, batPath, processName, env)
